#include "head.h"

#define UDP_SERVER_IP_STR "192.168.31.13"
#define UDP_SERVER_PORT   50000

int InitUdpServer( const char strServerIP[], const int ServerPort )
{
    int ServerSockFd;
    ServerSockFd = socket( AF_INET, SOCK_DGRAM, 0 );
    if ( -1 == ServerSockFd )
    {
        perror( "fail socket @ InitUpdServer" );
        return -1;
    }

    struct sockaddr_in ServerAddr;
    ServerAddr.sin_family = AF_INET;
    ServerAddr.sin_port = htons ( UDP_SERVER_PORT );
    ServerAddr.sin_addr.s_addr = inet_addr( UDP_SERVER_IP_STR );

    int Ret;
    Ret = bind( ServerSockFd, (struct sockaddr*)&ServerAddr, sizeof(ServerAddr) );
    if ( -1 == Ret )
    {
        perror( "fail bind @ InitUpdServer" );
        return -1;
    }

    return ServerSockFd;

}

ssize_t RecvfromClint( const int ServerSockFd, const long SizeRecv, 
                        char strRecv[], char strClintIp[], int *pClintPort )
{
    struct sockaddr_in ClintAddr;
    socklen_t ClintAddrLen = sizeof(ClintAddr);

    ssize_t SizeRet;
    SizeRet = recvfrom( ServerSockFd, strRecv, SizeRecv, 0, 
                        (struct sockaddr *)&ClintAddr, &ClintAddrLen );
    if ( -1 == SizeRet )
    {
        perror( "fail recvfrom @ RecvfromClint" );
        return -1;
    }
    
    strcpy( strClintIp, inet_ntoa(ClintAddr.sin_addr) );
    *pClintPort = ntohs(ClintAddr.sin_port);

    return SizeRet;
}

int main(int argc, char const *argv[])
{
    int ServerSockFd;
    ServerSockFd = InitUdpServer( UDP_SERVER_IP_STR, UDP_SERVER_PORT);

    char strRecvBuff[1024] = {0};
    char strClintIp[30]    = {0};
    int ClintPort = 0;


    while (1)
    {
        ssize_t SizeRecv;
        SizeRecv = RecvfromClint( ServerSockFd, sizeof(strRecvBuff),
                                    strRecvBuff, strClintIp, &ClintPort );
        if ( -1 == SizeRecv)
        {
            perror( "fail RecvfromClint" );
            return -1;
        }

        printf( "Recvfrom %s : %d --- #%ld bytes --- %s\n", 
                strClintIp, ClintPort, SizeRecv, strRecvBuff );
        
        memset( strRecvBuff, 0, sizeof(strRecvBuff) );
        memset( strClintIp, 0, sizeof(strClintIp) );
        ClintPort = 0;

    }

    close( ServerSockFd );

    return 0;
}

/*
程序功能
    创建 UDP服务器进程, 接收从 UDP客户端进程 的 UDP报文, 并显示 UDP客户端 的 IP地址, 端口, 数据内容.

涉及函数
    socket()
    bind()
        struct sockaddr_in
        htons()
        inet_addr()
    recvfrom()

程序流程
    创建 UDP数据报套接字
    绑定本机为 UDP服务器
    循环接收来自 UDP客户端 的 UDP报文

知识要点
    初始化 UDP Server 的原子操作.

测试流程
    
*/